package com.example.demo.service;

import com.example.demo.domain.repository.UserRepository;
import com.example.demo.domain.User;
import com.example.demo.util.JWTTokenUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Service
public class UserService {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Qualifier("userDetailsServiceImpl")
    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private JWTTokenUtil jwtTokenUtil;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    BCryptPasswordEncoder bCryptPasswordEncoder;

    /**
    * @Description: 用户登录
    * @Param:  username: 用户名
     * @Param: password: 用户密码
    * @return:  用户信息列表
    * @Author: wangze
    */
    public List<Object> login(String username, String password ) {
        //进入UsernamePasswordAuthenticationToken验证
        UsernamePasswordAuthenticationToken upToken = new UsernamePasswordAuthenticationToken( username, password );
//        System.out.println("login1");
        //由AuthenticationManager来生成Authentication，通过AuthenticationManager的authenticate方法校验uptoken是否正确，如果失败则直接跳异常
        /**
         * Authentication是一个接口，其中getPrincipal()方法返回Principal身份信息类，getCredentials()方法返回凭据类
         * Principal身份信息类，通常是UserDetail
         * Credential凭据类，通常是密码
         */
        final Authentication authentication = authenticationManager.authenticate(upToken);
//        System.out.println("login2");
        SecurityContextHolder.getContext().setAuthentication(authentication);
        //System.out.println("login3");
        final UserDetails userDetails = userDetailsService.loadUserByUsername( username );
        //System.out.println("login4");
        String token=jwtTokenUtil.generateToken(userDetails);
        //System.out.println("login5");
        User user = userRepository.findByUsername(username);
        List<Object> list = new ArrayList<>();
        list.add(token);
        list.add(user.getUserId());
        list.add(user.getAuth());
        list.add(user.getName());
        list.add(user.getDepartment());
        list.add(user.getPhone());
        list.add(user.getSex());
        list.add(user.getAge());
        list.add(user.getRoleId());
        return list;
    }

    /**
    * @Description: 添加用户
    * @Param:  user: 用户信息
    * @return:  用户实体
    * @Author: wangze
    */
    public User addUser(User user){
        if(userRepository.findByUsername(user.getUsername())!=null)
            return null;
        user.setPassword(bCryptPasswordEncoder.encode(user.getUsername()));
        user.setAuth("普通职工");
        return userRepository.save(user);
    }

    /**
     * @Description: 根据ID删除用户
     * @Param:  id：用户ID
     * @return:  无
     * @Author: wangze
     */
    public void deleteUserById(Integer id){
        userRepository.deleteUserByUserId(id);
    }

    /**
    * @Description: 修改用户信息
    * @Param:  user：前段传递的用户实体
    * @return:  无
    * @Author: wangze
    */
    public User updateUser(User user){
        return userRepository.save(user);
    }

    /**
     * @Description: 根据用户ID查找用户
     * @Param:  user_id: 职工ID
     * @return:  用户实体
     * @Author: wangze
     */
    public User getById(Integer user_id){
        return userRepository.findUserByUserId(user_id);
    }

    /**
    * @Description: 根据职工工号查找用户
    * @Param:  username: 职工工号即用户名
    * @return:  用户实体
    * @Author: wangze
    */
    public User getByUsername(String username) {
        return userRepository.findByUsername(username);
    }

    /**
    * @Description: 超级管理员重置用户密码
    * @Param:  id: 用户ID
    * @return:  提示信息
    * @Author: wangze
    */
    public String resetPassword(Integer id){
        User user = userRepository.findUserByUserId(id);
        user.setPassword(bCryptPasswordEncoder.encode(user.getUsername()));
        userRepository.save(user);
        return "修改成功";
    }

    /**
    * @Description: 刷新用户token
    * @Param:  token: 用户当前token
    * @return:  刷新后的token
    * @Author: wangze
    */
    public String refreshUserToken(String token){
        Integer flag = jwtTokenUtil.canTokenBeRefreshed(token);
        if( flag == 1){
            return jwtTokenUtil.refreshToken(token);
        }
        else if(flag == 0)
            return token;
        return null;
    }

    /**
    * @Description: 获取全部用户
    * @Param:  无
    * @return:  全部用户列表
    * @Author: wangze
    */
    public List<User> getAllUsers(){
        return userRepository.findAll();
    }

    /**
    * @Description: 根据三种关键字查询用户
    * @Param:  无
    * @return:  对应用户列表
    * @Author: wangze
    */
    public List<User> getUsersByKeyword(String keyword){
        return userRepository.findByUsernameContainingOrNameContainingOrDepartmentContaining(keyword,keyword,keyword);
    }

    /**
    * @Description:  根据职工工号查找用户(模糊查询)
    * @Param: workNumber: 职工工号
    * @return: 相应用户列表
    * @Author: wangze
    */
    public List<User> findUserByWorkNumber(String workNumber){
        return userRepository.findByUsernameContaining(workNumber);
    }

    /**
    * @Description: 根据职工姓名查找用户
    * @Param:  object: 职工姓名
    * @return: 相应用户列表
    * @Author: wangze
    */
    public List<User> findUserByName(String name){
        return userRepository.findByNameContaining(name);
    }

    /**
    * @Description: 根据职工部门查找用户
    * @Param:  department: 职工部门
    * @return:  相应用户列表
    * @Author: wangze
    */
    public List<User> findUserByDepartment(String department){
        return userRepository.findByDepartmentContaining(department);
    }
}
